﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Configuration;
using Ashlen.Portal.Data.SqlServer;
using Ashlen.Portal.Core;
using Ashlen.Portal.Core.DataInterfaces;


namespace Ashlen.Utility.NewsService
{
    /// <summary>
    /// This is the host service for virtual news feed services.
    /// It loads all the news sources from the database and creates
    /// a virtual instance of the NewsFeedService for each source.
    /// </summary>
    /// <remarks>
    /// Author: Shailen Sukul
    /// Date: 08 Oct 2008
    /// </remarks>
    partial class NewsFeedServiceHost : ServiceBase
    {
        #region Variables
        private List<Thread> threadArray = new List<Thread>();
        private List<IService> instanceArray = new List<IService>();
        private INewsDao _dao;
        /// delegate used when invoke the OnStop method asynchronous during service shut down.
        /// </summary>
        public delegate void OnStopDelegate();
        #endregion

        #region Constructor
        public NewsFeedServiceHost() {
            InitializeComponent();
            _dao = new NewsDao();
        }

        #endregion

        public void StartService(string[] args) {
            OnStart(args);
        }

        public void StopService() {
            OnStop();
        }

        protected override void OnStart(string[] args) {
            try {
                IService instance = null;
                int interval = Convert.ToInt32(ConfigurationManager.AppSettings["TimerInterval"]);
                List<NewsSource> newsSources = _dao.GetNewsSources() as List<NewsSource>;
                Log.LogEvent(EventLogEntryType.Information, string.Format("{0} services will be started for as many sources.", newsSources.Count));
                foreach (NewsSource newsSource in newsSources) {
                    instance = new NewsFeedService(newsSource.Id, interval);
                    //initialize the service
                    instance.Initialize(null);
                    instanceArray.Add(instance);

                    //create SecuritySwitchThread object to process the service
                    ThreadStart ts = new ThreadStart(instance.Start);
                    SecuritySwitchThread sst = new SecuritySwitchThread(ts, null);
                    //start the SecuritySwitchThread's thread.
                    sst.Start();
                    threadArray.Add(sst.BaseThread);
                }
            }
            catch (Exception ex) {
                //write to the event log
                Log.LogEvent(EventLogEntryType.Error, ex.ToString());
            }

        }

        protected override void OnStop() {
            foreach (object o in instanceArray) {
                try {
                    IService service = (IService)o;
                    if (service != null) {
                        //invoke the delegate asynchronous to stop each started service.
                        OnStopDelegate osd = new OnStopDelegate(service.Stop);
                        osd.BeginInvoke(null, null);
                    }
                }
                catch (Exception ex) {
                    //write to the event log
                    Log.LogEvent(EventLogEntryType.Error, ex.ToString());
                }
            }

            //give sometime for the each instance to shut down gracefully
            Thread.Sleep(5000);
            foreach (object o in threadArray) {
                try {
                    Thread t = (Thread)o;
                    if (t != null) {
                        //if the thread is still live at this point, shut it down forcefully.
                        if (t.IsAlive == true) {
                            t.Abort();
                        }
                    }
                }
                catch (Exception ex) {
                    //write to the event log
                    Log.LogEvent(EventLogEntryType.Error, ex.ToString());
                }
            }
        }
    }
}
